/**
 * 
 */
package profile.report;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import profile.result.MethodResult;
import profile.result.ParamResult;
import profile.result.ContextResult;
import profile.result.StoreResult;
import profile.result.ProfileResults;

/**
 * @author ductrung.tran
 *
 */
public class ResultsReport {

	private String firstName;
	private String secondName;
	
	private Map<String, ContextResultReport> contextResultReportMap = new HashMap<String, ContextResultReport>();
	
	public void addFirstResults(ProfileResults actualResults) {
		this.firstName = actualResults.getName();
		
		for (ContextResult contextResult : actualResults.getContextResultMap().values()) {
			addFirstContextResult(contextResult);
		}
	}

	private void addFirstContextResult(ContextResult contextResult) {
		ContextResultReport contextResultReport = new ContextResultReport();
		contextResultReport.setName(contextResult.getName());
		for (StoreResult storeResult : contextResult.getStoreResultMap().values()) {
			addFirstStoreResult(storeResult, contextResultReport);
		}
		
		addContextResultReport(contextResultReport);
	}

	private void addContextResultReport(
			ContextResultReport contextResultReport) {
		contextResultReportMap.put(contextResultReport.getName(), contextResultReport);
	}

	private void addFirstStoreResult(StoreResult storeResult,
									ContextResultReport contextResultReport) {
		StoreResultReport storeResultReport = new StoreResultReport();
		storeResultReport.setStore(storeResult.getStore());
		for (MethodResult methodResult : storeResult.getMethodResultMap().values()) {
			addFirstMethodResult(methodResult, storeResultReport);
		}
		
		contextResultReport.addStoreResultReport(storeResultReport);
	}

	private void addFirstMethodResult(MethodResult methodResult,
			StoreResultReport storeResultReport) {
		MethodResultReport methodResultReport = new MethodResultReport();
		methodResultReport.setMethod(methodResult.getName());
		
		for (ParamResult paramResult : methodResult.getParamResultMap().values()) {
			addFirstParamResult(paramResult, methodResultReport);
		}
		
		storeResultReport.addMethodResultReport(methodResultReport);
	}

	private void addFirstParamResult(ParamResult paramResult,
			MethodResultReport methodResultReport) {
		ParamResultReport paramResultReport = new ParamResultReport();
		paramResultReport.setParam(paramResult.getName());
		paramResultReport.addParamItems(paramResult.getResultItemList());
		
		methodResultReport.addFirstParamResultReport(paramResultReport);
	}

	
	public void addSecondResults(ProfileResults otherResults) {
		this.secondName = otherResults.getName();
		
		for (ContextResult contextResult : otherResults.getContextResultMap().values()) {
			addSecondContextResult(contextResult);
		}
	}

	private void addSecondContextResult(ContextResult contextResult) {
		ContextResultReport existResultReport = (ContextResultReport) contextResultReportMap.get(contextResult.getName());
		if (existResultReport == null) {
			existResultReport = new ContextResultReport();
			existResultReport.setName(contextResult.getName());
			contextResultReportMap.put(existResultReport.getName(), existResultReport);
		}
		
		for (StoreResult storeResult : contextResult.getStoreResultMap().values()) {
			addSecondStoreResult(storeResult, existResultReport);
		}
		
	}

	private void addSecondStoreResult(StoreResult storeResult, ContextResultReport contextResultReport) {
		StoreResultReport existResultReport = contextResultReport.getStoreResultReport(storeResult.getStore());
		if (existResultReport == null) {
			existResultReport = new StoreResultReport();
			existResultReport.setStore(storeResult.getStore());
			contextResultReport.addStoreResultReport(existResultReport);
		}
		
		for (MethodResult methodResult : storeResult.getMethodResultMap().values()) {
			addSecondMethodResult(methodResult, existResultReport);
		}
	}

	private void addSecondMethodResult(MethodResult methodResult,
			StoreResultReport storeResultReport) {
		MethodResultReport existResultReport = storeResultReport.getMethodResultReport(methodResult.getName());
		if (existResultReport == null) {
			existResultReport = new MethodResultReport();
			existResultReport.setMethod(methodResult.getName());
			storeResultReport.addMethodResultReport(existResultReport);
		}
		
		for (ParamResult paramResult : methodResult.getParamResultMap().values()) {
			addSecondParamResult(paramResult, existResultReport);
		}
	}

	private void addSecondParamResult(ParamResult paramResult,
			MethodResultReport methodResultReport) {
		ParamResultReport existResultReport = new ParamResultReport();
		existResultReport.setParam(paramResult.getName());
		existResultReport.addParamItems(paramResult.getResultItemList());
		
		methodResultReport.addSecondParamResultReport(existResultReport);
		
		
	}
	
	public String getFirstName() {
		return firstName;
	}
	
	public String getSecondName() {
		return secondName;
	}
	
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append(firstName).append('\n');
		builder.append(secondName).append('\n');
		for (ContextResultReport contextResultReport : contextResultReportMap.values()) {
			builder.append(contextResultReport.toString()).append('\n');
		}
		
		return builder.toString();
	}
	
	public Collection<ContextResultReport> getContextResultReports() {
		return contextResultReportMap.values();
	}
}
